{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Generating an OpenCL Kernel using Textual Templating"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A more advanced, but also less lightweight, alternative is the usage of a so-called templating engine, as it is being used to generate web pages.\n",
    "\n",
    "This offers tremendous flexibility in generation, including the possibility for full flow control, allowing applications such as loop unrolling.\n",
    "\n",
    "In the example below, we use a templating engine called 'Mako':"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from mako.template import Template"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "tpl = Template(r\"\"\"\n",
    "    __kernel void ${name}(${arguments})\n",
    "    {\n",
    "      int lid = get_local_id(0);\n",
    "      int gsize = get_global_size(0);\n",
    "      int work_group_start = get_local_size(0)*get_group_id(0);\n",
    "      long i;\n",
    "\n",
    "      for (i = work_group_start + lid; i < n; i += gsize)\n",
    "      {\n",
    "        %for i_unroll in range(n_unroll):\n",
    "            ${operation};\n",
    "            %if i_unroll + 1 < n_unroll:\n",
    "                i += gsize;\n",
    "            %endif\n",
    "        %endfor\n",
    "      }\n",
    "    }\n",
    "\"\"\", strict_undefined=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "    __kernel void scale(float *y, float a, float *x)\n",
      "    {\n",
      "      int lid = get_local_id(0);\n",
      "      int gsize = get_global_size(0);\n",
      "      int work_group_start = get_local_size(0)*get_group_id(0);\n",
      "      long i;\n",
      "\n",
      "      for (i = work_group_start + lid; i < n; i += gsize)\n",
      "      {\n",
      "            y[i] = a*x[i];\n",
      "                i += gsize;\n",
      "            y[i] = a*x[i];\n",
      "      }\n",
      "    }\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(tpl.render(\n",
    "    name=\"scale\",\n",
    "    arguments=\"float *y, float a, float *x\",\n",
    "    operation=\"y[i] = a*x[i]\",\n",
    "    n_unroll=2,\n",
    "))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 0
}